#import <TelephonyUI/TPTopLockBar.h>
#import <SpringBoard/SBPowerDownView.h>
#import <TelephonyUI/TPBottomLockBar.h>
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <SpringBoard/SpringBoard.h>
#import <objc/runtime.h>
#import "substrate.h"

#define RB_AUTOBOOT 0

@protocol GPowerObject

- (void)GP_animateIn;
- (void)GP_animateOut;
- (id)GP_initWithFrame:(CGRect)frame;

@end

typedef void (*power_slider_action)();

@interface PowerSliderBar : TPTopLockBar {
@private
	power_slider_action _action;
}

- (id)initWithAction:(power_slider_action)action frame:(CGRect)frame knobColor:(NSInteger)knobColor;

@end

@implementation PowerSliderBar : TPTopLockBar

- (id)initWithAction:(power_slider_action)action frame:(CGRect)frame knobColor:(NSInteger)knobColor {
	if(self = [super initWithFrame:frame knobColor:knobColor]) {
		_action = action;
	}

	return self;
}

- (void)unlock {
	_action();
}

@end

PowerSliderBar *rebooter = nil;
PowerSliderBar *respring = nil;

// Actions

void respringDevice() {
	system("killall SpringBoard");
}

void rebootDevice() {
	reboot(RB_AUTOBOOT);
}

static void GPower_SBPowerDownView_animateIn(SBPowerDownView<GPowerObject> *self, SEL _cmd) {
        TPTopLockBar *powerDown = (TPTopLockBar *)object_getIvar(self, class_getInstanceVariable([self class], "_lockView"));
        [powerDown setFontSize:21.0f];
        [powerDown setLabel:@"Slide To Power Off"];

	[self GP_animateIn];

        rebooter = [[[PowerSliderBar alloc] initWithAction:rebootDevice frame:CGRectMake(0 - [[UIScreen mainScreen] bounds].size.width, 20 + 97, [[UIScreen mainScreen] bounds].size.width, 97.0f) knobColor:0] autorelease];
        [rebooter setFontSize:21.0f];
        [rebooter setLabel:@"Slide To Reboot"];
        [self addSubview:rebooter];
        [rebooter startAnimating];

        respring = [[[PowerSliderBar alloc] initWithAction:respringDevice frame:CGRectMake([[UIScreen mainScreen] bounds].size.width, 20 + 97 + 97, [[UIScreen mainScreen] bounds].size.width, 97.0f) knobColor:1] autorelease];
        [respring setFontSize:21.0f];
        [respring setLabel:@"Slide To Respring"];
        [self addSubview:respring];
        [respring startAnimating];

		
	[UIView beginAnimations:@"GPOWER" context:NULL];
	[UIView setAnimationDuration:0.5];
	rebooter.center = CGPointMake([[UIScreen mainScreen] bounds].size.width / 2, rebooter.center.y); 
	respring.center = CGPointMake([[UIScreen mainScreen] bounds].size.width / 2, respring.center.y);
	[UIView commitAnimations];
}

static void GPower_SBPowerDownView_animateOut(SBPowerDownView<GPowerObject> *self, SEL _cmd) {
	[self GP_animateOut];

	[UIView beginAnimations:@"GPOWEROUT" context:NULL];
	[UIView setAnimationDuration:0.5];
	
	respring.center = CGPointMake([[UIScreen mainScreen] bounds].size.width + ([[UIScreen mainScreen] bounds].size.width / 2), respring.center.y);
	rebooter.center = CGPointMake(0 - [[UIScreen mainScreen] bounds].size.width, rebooter.center.y);
	
	[UIView commitAnimations];

	[respring stopAnimating];
	[rebooter stopAnimating];

	[self performSelector:@selector(_removeSliders) withObject:nil afterDelay:0.5];
}

static void removeSliders() {
	[rebooter removeFromSuperview];
	[respring removeFromSuperview];
}

static id GPower_SBPowerDownView_initWithFrame(SBPowerDownView<GPowerObject> *self, SEL _cmd, CGRect frame) {
	id _self = [self GP_initWithFrame:frame];

	class_addMethod([self class], @selector(_removeSliders), (IMP)removeSliders, "v@:");
	
	return _self;
}

extern "C" void GPower() {
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

	Class _SpringBoard = objc_getClass("SpringBoard");
	Class _SBPowerDownView = objc_getClass("SBPowerDownView");
	if(_SpringBoard == nil || _SBPowerDownView == nil) return;

	MSHookMessage(_SBPowerDownView, @selector(initWithFrame:), (IMP)GPower_SBPowerDownView_initWithFrame, "GP_");
	MSHookMessage(_SBPowerDownView, @selector(animateIn), (IMP)GPower_SBPowerDownView_animateIn, "GP_");
	MSHookMessage(_SBPowerDownView, @selector(animateOut), (IMP)GPower_SBPowerDownView_animateOut, "GP_");

	[pool release];
}
